/*
	*@brief			：互斥锁初始化，上锁，解锁，销毁
	*@param[mutex]	:一个 pthread_mutex_t 类型指针， 指向需要进行初始化操作的互斥锁对象；
	*@param[attr]	:一个 pthread_mutexattr_t 类型指针，指向一个 pthread_mutexattr_t 类型对象，该对象用于定义互斥锁的属性（在 12.2.6 小计中介绍），若将参数 attr 设置为 NULL，则表示将互斥锁的属性设置为默认值，
					在这种情况下其实就等价于 PTHREAD_MUTEX_INITIALIZER 这种方式初始化，而不同之处在于，使用宏不进行错误检查。


	*@return 		:成功返回 0；失败将返回一个非 0 的错误码。
	*@others		:上锁：
					调用 pthread_mutex_lock()函数对互斥锁进行上锁，如果互斥锁处于未锁定状态，则此次调用会上锁成功，函数调用将立马返回；
					如果互斥锁此时已经被其它线程锁定了，那么调用 pthread_mutex_lock()会一直阻塞，直到该互斥锁被解锁，到那时，调用将锁定互斥锁并返回。

					解锁：
					调用 pthread_mutex_unlock()函数将已经处于锁定状态的互斥锁进行解锁。以下行为均属错误：
					- 对处于未锁定状态的互斥锁进行解锁操作；
					- 解锁由其它线程锁定的互斥锁。
					如果有多个线程处于阻塞状态等待互斥锁被解锁 ，当互斥锁被当前锁定它的线程调用pthread_mutex_unlock()函数解锁后，这些等待着的线程都会有机会对互斥锁上锁，但无法判断究竟哪个线程会如愿以偿！

					销毁：
					- 不能销毁还没有解锁的互斥锁，否则将会出现错误；
					-  没有初始化的互斥锁也不能销毁。
					被 pthread_mutex_destroy()销毁之后的互斥锁，就不能再对它进行上锁和解锁了，需要再次调用pthread_mutex_init()对互斥锁进行初始化之后才能使用。
*/

/*
	互斥锁初始化
	int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
	上锁
	int pthread_mutex_lock(pthread_mutex_t *mutex);
	解锁
	int pthread_mutex_unlock(pthread_mutex_t *mutex);
	以非阻塞方式上锁
	int pthread_mutex_trylock(pthread_mutex_t *mutex);
	销毁
	int pthread_mutex_destroy(pthread_mutex_t *mutex);
*/

/*	互斥锁初始化
	1.
	# define PTHREAD_MUTEX_INITIALIZER 	{ { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } }
	所以由此可知，使用 PTHREAD_MUTEX_INITIALIZER 宏初始化互斥锁的操作如下：
	pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
	2.
	使用 pthread_mutex_init()函数对互斥锁进行初始化示例：
	pthread_mutex_t mutex;
	pthread_mutex_init(&mutex, NULL);
	或者：
	pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
	pthread_mutex_init(mutex, NULL);


	当互斥锁已经被其它线程锁住时，调用 pthread_mutex_lock()函数会被阻塞，直到互斥锁解锁；如果线程不希望被阻塞，可以使用 pthread_mutex_trylock()函数；
	调用 pthread_mutex_trylock()函数尝试对互斥锁进行加锁，如果互斥锁处于未锁住状态，那么调用 pthread_mutex_trylock()将会锁住互斥锁并立马返回，
	如果互斥锁已经被其它线程锁住，调用 pthread_mutex_trylock()加锁失败，但不会阻塞，而是返回错误码 EBUSY。
*/

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>

static pthread_mutex_t mutex;

static int g_count = 0;

static void *new_thread_start(void *arg)
{
	int loops = *((int *)arg);
	int l_count, j;

	for (j = 0; j < loops; j++)
	{
		pthread_mutex_lock(&mutex); //互斥锁上锁

		// while(pthread_mutex_trylock(&mutex)); //以非阻塞方式上锁a

		l_count = g_count;
		l_count++;
		g_count = l_count;
		pthread_mutex_unlock(&mutex); //互斥锁解锁
	}

	return (void *)0;
}

static int loops;

int main(int argc, char *argv[])
{
	pthread_t tid1, tid2;
	int ret;

	if (argc < 2)
	{
		loops = 10000000;
	}
	else
	{
		loops = atoi(argv[1]);
	}

	//初始化互斥锁
	ret = pthread_mutex_init(&mutex, NULL);
	if (ret)
	{
		fprintf(stderr, "pthread_mutex_init error:%s\n", strerror(ret));
		exit(-1);
	}

	//创建1号线程
	ret = pthread_create(&tid1, NULL, new_thread_start, &loops);
	if (ret)
	{
		fprintf(stderr, "pthread_create 1 error:%s\n", strerror(ret));
		exit(-1);
	}

	//创建2号线程
	ret = pthread_create(&tid2, NULL, new_thread_start, &loops);
	if (ret)
	{
		fprintf(stderr, "pthread_create 2 error:%s\n", strerror(ret));
		exit(-1);
	}

	//回收1号线程
	ret = pthread_join(tid1, NULL);
	if (ret)
	{
		fprintf(stderr, "pthread_join 1 error:%s\n", strerror(ret));
		exit(-1);
	}

	//回收2号线程
	ret = pthread_join(tid2, NULL);
	if (ret)
	{
		fprintf(stderr, "pthread_join 2 error:%s\n", strerror(ret));
		exit(-1);
	}

	printf("g_count=%d\n", g_count);

	//销毁互斥锁
	pthread_mutex_destroy(&mutex);

	exit(0);
}